/*  
  -- The Lime II Project -- 

  A tuplespaces-based middleware for coordinating agents and mobile hosts.
  Copyright (C) 2005.
  Gian Pietro Picco, Amy L. Murphy, Lorenzo Bellini.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received this copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 */

package lime2.trackerca;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Enumeration;

import lime2.LimeConstants;
import lime2.LimeServer;
import lime2.LimeServerID;
import lime2.Serializer;
import lime2.ca.EngMsg;
import lime2.trackerca.TrackerPlainCA;

/**
 * A "receiver" of remote unicast messages. It accepts as many new (TCP) connections as possible, receives remote 
 * ops and enqueues them.
 * 
 * @author Gian Pietro Picco
 * @author Amy Murphy
 * @author Lorenzo Bellini 
 */

class TrackerPlainUnicastReceiver extends Thread
{
	// private data members	
	private ServerSocket SSock;
	private boolean shutdown;
	private DatagramSocket resock ;

	/**
	 * Constructor method. 
	 * 
	 * @param SSock server socket
	 */
	TrackerPlainUnicastReceiver(ServerSocket SSock)
	{
		super();
		this.SSock = SSock;
		this.shutdown = false;
		
	}
	TrackerPlainUnicastReceiver(ServerSocket SSock, DatagramSocket resock)
	{
		super();
		this.SSock = SSock;
		this.resock= resock;
		this.shutdown = false;
		
	}
	/**
	 * Run method. 
	 */
	public void run()
	{
		// accepts new connections and serves them	
		while (!shutdown)
		{
			try 
			{
				Socket newSocket = SSock.accept(); 
				Connection.add(newSocket);
				new UnicastServant(newSocket).start();
			}
			catch (Exception ioe) { ioe.printStackTrace(); }
		} 

		// closes server socket
		try { SSock.close(); } catch (IOException ioe) { ioe.printStackTrace(); }
	}

	/**
	 * Shuts the receiver down.
	 */
	void shutdown()
	{
		shutdown = true;	
	} 

}

/**
 * An instance of UnicastServant manages an incoming connection. The server-side policy is to close the connection as
 * "second": it is the client-side that chooses whether to keep the connection opened or not.
 */

 
class UnicastServant extends Thread
{
	// private data members	
	private Socket socket;	

	/**
	 * Constructor method.
	 * 
	 * @param socket to listen to
	 */
	UnicastServant(Socket socket)
	{
		super();
		this.socket = socket;	  
	}

	/**
	 * Run method.
	 */
	public void run()
	{
		// initializations	
		ObjectInputStream ois = null;	
		boolean close = false; 	

		// opens object stream
		try { ois = new ObjectInputStream(socket.getInputStream()); }
		catch (IOException ioe) { close = true; } 

		// main routine
		while (!close) 
		{ 
			try 
			{ 
				Object o = ois.readObject(); 
				TrackerPlainCA.queue.add(o);
			}
			catch (ClassNotFoundException cnfe) { cnfe.printStackTrace(); }
			catch (IOException ioe) { close = true; } 
		}

		// must close connection
		try { if (ois != null) ois.close(); } catch (IOException ioe) { }
		try { Connection.remove(socket); } catch (IOException ioe) { }
		try { socket.close(); } catch (IOException ioe) { }
	}

} 
